<!DOCTYPE html>
<html lang="en">

<head>
    <meta charset="UTF-8">
    <!-- 设置页面在浏览器标签页显示的标题 -->
    <title>方案5-实现上传文件夹进行树形解析</title>
</head>

<body>
<input type="file" id="fileInput" webkitdirectory directory multiple/>
<script>

    /**
     * 这段代码的目的是实现上传文件夹并对其进行树形解析，因此需要一个包含多个文件和子文件夹的示例文件夹，以下是一个示例文件夹结构：
     * cmyshare-文件夹
     * ├── subfolder1
     * │   ├── file1.txt
     * │   └── file2.txt
     * ├── subfolder2
     * │   ├── image1.jpg
     * │   └── image2.png
     * └── rootfile.txt
     *
     * 返回数据：
     * {"parentFileName":null,"fileName":"cmyshare-文件夹","nameUrlMap":{},"sonFileList":[{"parentFileName":"cmyshare-文件夹","fileName":"cmyshare-文件夹","nameUrlMap":{},"sonFileList":[{"parentFileName":"cmyshare-文件夹","fileName":"subfolder2","nameUrlMap":{},"sonFileList":[{"parentFileName":"subfolder2","fileName":"屏幕截图 2024-11-27 230650.png","nameUrlMap":{"屏幕截图 2024-11-27 230650.png":"https://www.baidu.com/imageundefined.jpg"},"sonFileList":[]},{"parentFileName":"subfolder2","fileName":"屏幕截图 2024-12-08 235935.png","nameUrlMap":{"屏幕截图 2024-12-08 235935.png":"https://www.baidu.com/imageundefined.jpg"},"sonFileList":[]}]},{"parentFileName":"cmyshare-文件夹","fileName":"subfolder1","nameUrlMap":{},"sonFileList":[{"parentFileName":"subfolder1","fileName":"屏幕截图 2024-11-27 230650.png","nameUrlMap":{"屏幕截图 2024-11-27 230650.png":"https://www.baidu.com/imageundefined.jpg"},"sonFileList":[]},{"parentFileName":"subfolder1","fileName":"屏幕截图 2024-12-08 235935.png","nameUrlMap":{"屏幕截图 2024-12-08 235935.png":"https://www.baidu.com/imageundefined.jpg"},"sonFileList":[]}]}]}]}
     */

    /**
     * 定义一个类，用于表示文件树节点。
     * 每个节点包含父级文件夹名称、当前文件夹名称、文件数据和子级文件夹。
     */
    class FileTreeNode {
        constructor() {
            // 父级文件夹名称，初始化为null，可以根据实际情况赋值
            this.parentFileName = null;
            // 当前文件夹名称，初始为空字符串，后续按需赋值
            this.fileName = '';
            // 当前文件夹中文件数据，使用JavaScript的对象（类似Java中的Map）来模拟键值对，初始为空对象
            this.nameUrlMap = {};
            // 子级文件夹，使用数组（类似Java中的List）来存放子节点对象，初始为空数组
            this.sonFileList = [];
        }
    }

    document.getElementById('fileInput').addEventListener('change', async function (e) {
        const fileList = e.target.files;
        const rootTreeNode = await buildFolderTree(fileList);
        const fileTreeJson = JSON.stringify(rootTreeNode);
        console.log(fileTreeJson);
        // 可以在这里将fileTreeJson发送给后端或者进行其他处理
    });

    async function buildFolderTree(files) {
        if (!files || !files.length) {
            return null;
        }
        // 用于存储解析后的文件夹对象，以路径为键，节点对象为值
        const folderMap = {};
        // 先处理所有文件，构建文件和文件夹节点基础结构
        for (const file of files) {
            const pathSegments = file.webkitRelativePath.split('/');
            let currentFolder = folderMap[''];
            if (!currentFolder) {
                currentFolder = new FileTreeNode();
                currentFolder.fileName = 'cmyshare-文件夹';
                folderMap[''] = currentFolder;
            }
            for (let j = 0; j < pathSegments.length - 1; j++) {
                const segment = pathSegments[j];
                let subFolder = currentFolder.sonFileList.find(f => f.fileName === segment);
                if (!subFolder) {
                    subFolder = new FileTreeNode();
                    subFolder.parentFileName = currentFolder.fileName;
                    subFolder.fileName = segment;
                    currentFolder.sonFileList.push(subFolder);
                }
                currentFolder = subFolder;
            }
            const fileTreeNode = buildFileNode(file);
            currentFolder.sonFileList.push(fileTreeNode);
        }
        const rootFolder = Object.values(folderMap).find(f => f.parentFileName === null);
        return rootFolder;
    }

    function buildFileNode(file) {
        const fileTreeNode = new FileTreeNode();
        fileTreeNode.parentFileName = getParentFolderName(file.webkitRelativePath);
        fileTreeNode.fileName = file.name;

//    fileTreeNode.nameUrlMap[file.name] = file.webkitRelativePath;
        //将file的字节流调用后端接口，得到文件url
        fileTreeNode.nameUrlMap[file.name] = getUrlByFile(file)
        return fileTreeNode;
    }

    function getParentFolderName(path) {
        const segments = path.split('/');
        return segments[segments.length - 2] || '';
    }

    //  https://www.cnblogs.com/yinpengfei/p/17280585.html
    //  https://blog.csdn.net/qq_43331014/article/details/132527328https://blog.csdn.net/qq_43331014/article/details/132527328
    //  https://www.cnblogs.com/goloving/p/10415670.html
    function getUrlByFile(file) {

//    //el-upload文件上传事件
//    changeFile(file) {
//      let formData = new FormData()
//      formData.append('file', file.raw)// 传文件
//      axios({
//        method: 'post',
//        url: url, //此处为往后台发送请求的地址
//        data: formData,
//        headers: {
//          // "Content-Type": "multipart/form-data"
//          credentials: 'same-origin'
//        },
//        timeout: 20000,
//        //设置返回接受类型为blob
//        responseType: 'blob'
//      }).then(res => {
//        //返回值转成Blob类型
//        let blob = new Blob([res.data])
//      });
//    }

//    Js读本地文件到字节数组
//    var reader = new FileReader();
//    reader.readAsArrayBuffer(fileObj);
//    reader.onload = function () {
//      var byts = new Uint8Array(this.result);
//      var bytarr = [];
//      for (var i = 0; i < byts.length; i++) {
//        bytarr.push(byts[i]);
//      } }

        let bytes = file.size || [];
        return "https://www.baidu.com/image" + bytes.length + ".jpg";
    }
</script>
</body>

</html>